5 追隨者

小工具

小工具是在視圖中使用的可重複使用建構區塊,以物件導向的方式建立複雜且可配置的使用者介面元素。例如,日期選擇器小工具可以產生精美的日期選擇器,讓使用者選擇日期作為輸入。您只需在視圖中插入如下程式碼

<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget(['name' => 'date']) ?>

Yii 捆綁了許多小工具,例如主動表單選單jQuery UI 小工具Twitter Bootstrap 小工具。在下面,我們將介紹關於小工具的基本知識。如果您想了解特定小工具的用法,請參閱類別 API 文件。

使用小工具

小工具主要在視圖中使用。您可以呼叫 yii\base\Widget::widget() 方法在視圖中使用小工具。此方法採用組態陣列來初始化小工具,並傳回小工具的呈現結果。例如,以下程式碼插入一個日期選擇器小工具,該小工具配置為使用俄語並將輸入保留在 $modelfrom_date 屬性中。

<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
    'model' => $model,
    'attribute' => 'from_date',
    'language' => 'ru',
    'dateFormat' => 'php:Y-m-d',
]) ?>

某些小工具可以接受內容區塊,該內容區塊應包含在 yii\base\Widget::begin()yii\base\Widget::end() 的調用之間。例如,以下程式碼使用 yii\widgets\ActiveForm 小工具來產生登入表單。小工具將分別在呼叫 begin()end() 的位置產生開始和結束 <form> 標籤。介於兩者之間的所有內容都將按原樣呈現。

<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;
?>

<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>

    <?= $form->field($model, 'username') ?>

    <?= $form->field($model, 'password')->passwordInput() ?>

    <div class="form-group">
        <?= Html::submitButton('Login') ?>
    </div>

<?php ActiveForm::end(); ?>

請注意,與傳回小工具呈現結果的 yii\base\Widget::widget() 方法不同,yii\base\Widget::begin() 方法傳回小工具的實例,您可以使用它來建構小工具內容。

注意: 某些小工具將使用 輸出緩衝 在呼叫 yii\base\Widget::end() 時調整封閉的內容。因此,呼叫 yii\base\Widget::begin()yii\base\Widget::end() 預期在同一個視圖檔案中發生。不遵守此規則可能會導致意外輸出。

設定全域預設值

小工具類型的全域預設值可以透過 DI 容器設定

\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);

有關詳細資訊,請參閱依賴注入容器指南中的「實際用法」章節

建立小工具

可以根據需求以兩種不同的方式建立小工具。

1:使用 widget() 方法

若要建立小工具,請從 yii\base\Widget 擴充,並覆寫 yii\base\Widget::init() 和/或 yii\base\Widget::run() 方法。通常,init() 方法應包含初始化小工具屬性的程式碼,而 run() 方法應包含產生小工具呈現結果的程式碼。呈現結果可以直接由 run()「echoed」或作為字串傳回。

在以下範例中,HelloWidget 會對 HTML 進行編碼並顯示指派給其 message 屬性的內容。如果未設定該屬性,則預設會顯示「Hello World」。

namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class HelloWidget extends Widget
{
    public $message;

    public function init()
    {
        parent::init();
        if ($this->message === null) {
            $this->message = 'Hello World';
        }
    }

    public function run()
    {
        return Html::encode($this->message);
    }
}

若要使用此小工具,只需在視圖中插入以下程式碼

<?php
use app\components\HelloWidget;
?>
<?= HelloWidget::widget(['message' => 'Good morning']) ?>

有時,小工具可能需要呈現大量內容。雖然您可以將內容嵌入到 run() 方法中,但更好的方法是將其放在視圖中,並呼叫 yii\base\Widget::render() 來呈現它。例如,

public function run()
{
    return $this->render('hello');
}

2:使用 begin()end() 方法

這與上面的方法類似,但略有不同。以下是 HelloWidget 的變體,它採用包含在 begin()end() 呼叫中的內容,對其進行 HTML 編碼,然後顯示它。

namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class HelloWidget extends Widget
{
    public function init()
    {
        parent::init();
        ob_start();
    }

    public function run()
    {
        $content = ob_get_clean();
        return Html::encode($content);
    }
}

如您所見,PHP 的輸出緩衝區在 init() 中啟動,以便可以捕獲、處理和在 run() 中傳回 init()run() 呼叫之間的任何輸出。

資訊: 當您呼叫 yii\base\Widget::begin() 時,將建立小工具的新實例,並且將在小工具建構子結束時呼叫 init() 方法。當您呼叫 yii\base\Widget::end() 時,將呼叫 run() 方法,其傳回結果將由 end() 回顯。

以下程式碼示範如何使用這個新的 HelloWidget 變體

<?php
use app\components\HelloWidget;
?>
<?php HelloWidget::begin(); ?>

    sample content that may contain one or more <strong>HTML</strong> <pre>tags</pre>

    If this content grows too big, use sub views

    For e.g.

    <?php echo $this->render('viewfile'); // Note: here render() method is of class \yii\base\View as this part of code is within view file and not in Widget class file ?>

<?php HelloWidget::end(); ?>

預設情況下,小工具的視圖應儲存在 WidgetPath/views 目錄中的檔案中,其中 WidgetPath 代表包含小工具類別檔案的目錄。因此,假設小工具類別位於 @app/components 下,則上述範例將呈現視圖檔案 @app/components/views/hello.php。您可以覆寫 yii\base\Widget::getViewPath() 方法來自訂包含小工具視圖檔案的目錄。

最佳實務

小工具是以物件導向的方式重複使用視圖程式碼。

建立小工具時,您仍然應該遵循 MVC 模式。一般而言,您應該將邏輯保留在小工具類別中,並將呈現保留在視圖中。

小工具應設計為自我包含。也就是說,當使用小工具時,您應該能夠直接將其放入視圖中,而無需執行任何其他操作。如果小工具需要外部資源(例如 CSS、JavaScript、圖片等),這可能會很棘手。幸運的是,Yii 提供了對資源包的支援,可以用於解決問題。

當小工具僅包含視圖程式碼時,它與視圖非常相似。事實上,在這種情況下,它們唯一的區別在於小工具是可重新發佈的類別,而視圖只是您希望保留在應用程式中的純 PHP 腳本。

發現錯字或您認為此頁面需要改進?
在 github 上編輯 !